package com.huangkailong.designpattern.singleton;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.InvocationTargetException;

/**
 * 枚举方式的单例模式.
 *
 * @author huangkl
 * @since 1.0.0
 */
public enum EnumSingleton {
    /**
     * 实例
     */
    INSTANCE;

    private Object data;

    /**
     * 获取 {@link EnumSingleton} 实例.
     *
     * @return {@link EnumSingleton} 实例
     */
    public static EnumSingleton getInstance() {
        return INSTANCE;
    }

    /**
     * 测试.
     */
    public static void main(String[] args) {
        System.out.println("对象比较结果：");
        System.out.println(EnumSingleton.getInstance() == EnumSingleton.getInstance());
        try (ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
             ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream)
        ) {
            objectOutputStream.writeObject(EnumSingleton.getInstance());

            try (ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(
                byteArrayOutputStream.toByteArray());
                 ObjectInputStream objectInputStream = new ObjectInputStream(
                     byteArrayInputStream)) {
                Object o = objectInputStream.readObject();
                System.out.println("序列化结果:");
                System.out.println(EnumSingleton.getInstance() == o);
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

        try {
            EnumSingleton.class.getDeclaredConstructor().newInstance();
        } catch (InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
            e.printStackTrace();
        }
    }

    public Object getData() {
        return data;
    }

    public EnumSingleton setData(Object data) {
        this.data = data;
        return this;
    }
}
